package elijah.base;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Parcelable;
import android.provider.Settings;
import android.text.TextUtils;

import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.PermissionUtils;
import com.google.gson.Gson;
import com.tencent.mmkv.MMKV;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

import elijah.base.thread.Threads;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;

public class AppBase {
    public static long timeStamp = System.currentTimeMillis();
    private static volatile AppBase mInstance;
    private Context context;
    private final CompositeDisposable disposable = new CompositeDisposable();

    private AppBase() {

    }

    public static AppBase get() {
        if (mInstance == null) {
            synchronized (AppBase.class) {
                if (mInstance == null) {
                    mInstance = new AppBase();
                }
            }
        }
        return mInstance;
    }

    public AppBase permissions(String... permissions) {
        if (permissions.length <= 0) {
            return this;
        }
        PermissionUtils.permission(permissions).callback((isAllGranted, granted, deniedForever, denied) -> {
            if (!isAllGranted) {
                PermissionUtils.launchAppDetailsSettings();
            }
        }).request();

        return this;
    }


    void init(Context context) {
        this.context = context;
        MMKV.initialize(context);
        startTimeThread();
    }

    private void startTimeThread() {
        disposable.clear();
        disposable.add(Observable.interval(0, 1, TimeUnit.SECONDS)
                .compose(Threads.io2newThread())
                .subscribe(aLong -> {
                    timeStamp += 1000;
                }));
    }


    public Context getAppContext() {
        return context;
    }


    private Config config = new Config();

    public AppBase setConfig(Config config) {
        this.config = config;
        save(Constants.KEY_CONFIG, config);
        return this;
    }

    public Config getConfig() {
        return config;
    }

    public String getApiBaseUrl() {
        return "http://" + config.getIp() + ":" + config.getPort() + "/" + config.getProject() + "/";
    }

    public String getPicBaseUrl() {
        return "http://" + config.getFtpIp() + ":" + config.getPicPort() + "/";
    }


    public MMKV storage() {
        return MMKV.defaultMMKV(MMKV.MULTI_PROCESS_MODE, null);
    }


    public Gson getGson() {
        return GsonUtils.getGson();
    }

    public <T extends Parcelable>  void  save(String key, T value) {
        storage().encode(key, value);
    }

    public <T extends Parcelable> T load(String key, Class<T> clz) {
        return storage().decodeParcelable(key, clz);
    }

    public static long getTimeStamp() {
        return timeStamp;
    }

    public static void setTimeStamp(long time) {
        if (Math.abs(timeStamp - time) < 10_000) {
            return;
        }
        timeStamp = time;
        AppBase.get().startTimeThread();

    }

    @SuppressLint("HardwareIds")
    public synchronized String getAndroidId() {
        String androidId = null;
        try {
            androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
        } catch (Exception ignored) {
        }

        if (TextUtils.isEmpty(androidId)) {
            androidId = storage().decodeString(Constants.KEY_ANDROID_ID, "");
        }
        if (TextUtils.isEmpty(androidId)) {
            androidId = UUID.randomUUID().toString().replace("-", "");
            storage().decodeString(Constants.KEY_ANDROID_ID, androidId);
            storage().sync();
        }
        return androidId;
    }

    public static int getAppVersionCode() {
        return AppUtils.getAppVersionCode();
    }

    public static String getAppVersionName() {
        return AppUtils.getAppVersionName();
    }


}
